﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;

namespace CrazyClient
{
    /// <summary>
    /// Interaction logic for BpmControl.xaml
    /// </summary>
    public partial class BpmControl : UserControl
    {
        public BpmControl()
        {
            InitializeComponent();

           timeInfo= new TimeInfo();
            timeInfo.BPM = 92;
            timeInfo.TimeSigBottom = 4;
            timeInfo.TimeSigTop = 4;
        }
        public TimeInfo timeInfo;
       public long tickStart;
        public void Begin()
        {
             tickStart= DateTime.Now.Ticks;
      
        }
        #region SetupControlProperty
        public static readonly DependencyProperty SetupProperty =
            DependencyProperty.Register("Setup", typeof(string),
            typeof(BpmControl),
            new PropertyMetadata(OnSetupChanged));



        static private void OnSetupChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            BpmControl bpmControl=(BpmControl)obj;
            long barLength=bpmControl.timeInfo.Bar.Ticks;
            long tickStart=bpmControl.tickStart;

            string[] stAr=((string)e.NewValue).Split(new char[] { ' ' });
            Storyboard sb = new Storyboard();
            Int32AnimationUsingKeyFrames d = new Int32AnimationUsingKeyFrames();
            foreach (string st in stAr)
            {
                string data=st.Substring(1,st.Length-1);
                int dataInt=Int32.Parse(data);
                TimeSpan length;
                if (data[0] == 'Q')
                    length = bpmControl.timeInfo.Quarter;
                else
                    length = new TimeSpan(0,0,0,3,0);

                Int32KeyFrame k = new DiscreteInt32KeyFrame(dataInt,KeyTime.FromTimeSpan(length));
                d.KeyFrames.Add(k);
            }

            Storyboard info = new Storyboard();
            DoubleAnimationUsingKeyFrames b1 = new DoubleAnimationUsingKeyFrames();
            DoubleAnimationUsingKeyFrames b2 = new DoubleAnimationUsingKeyFrames();
            DoubleAnimationUsingKeyFrames b3 = new DoubleAnimationUsingKeyFrames();
            DoubleAnimationUsingKeyFrames b4 = new DoubleAnimationUsingKeyFrames();
            
            
            MediaTimeline mt1 = new MediaTimeline(new TimeSpan(0));
            MediaTimeline mt2 = new MediaTimeline(bpmControl.timeInfo.Quarter);
            MediaTimeline mt3 = new MediaTimeline(bpmControl.timeInfo.Half);
            MediaTimeline mt4 = new MediaTimeline(bpmControl.timeInfo.Quarter + bpmControl.timeInfo.Half);
            
            mt1.Source =new Uri("clave 1.wav",UriKind.Relative );
            mt2.Source = new Uri("clave 3.wav", UriKind.Relative);
            mt3.Source = new Uri("clave 3.wav", UriKind.Relative);
            mt4.Source = new Uri("clave 3.wav", UriKind.Relative);


            b1.KeyFrames.Add(new DiscreteDoubleKeyFrame(1, new TimeSpan(0)));
            b1.KeyFrames.Add(new DiscreteDoubleKeyFrame(0, bpmControl.timeInfo.Quarter));

            b2.KeyFrames.Add(new DiscreteDoubleKeyFrame(0, new TimeSpan(0)));
            b2.KeyFrames.Add(new DiscreteDoubleKeyFrame(1, bpmControl.timeInfo.Quarter));
            b2.KeyFrames.Add(new DiscreteDoubleKeyFrame(0, bpmControl.timeInfo.Half));

            b3.KeyFrames.Add(new DiscreteDoubleKeyFrame(0, new TimeSpan(0)));
            b3.KeyFrames.Add(new DiscreteDoubleKeyFrame(1, bpmControl.timeInfo.Half));
            b3.KeyFrames.Add(new DiscreteDoubleKeyFrame(0, bpmControl.timeInfo.Half+bpmControl.timeInfo.Quarter));

            b4.KeyFrames.Add(new DiscreteDoubleKeyFrame(0, new TimeSpan(0)));
            b4.KeyFrames.Add(new DiscreteDoubleKeyFrame(1, bpmControl.timeInfo.Half + bpmControl.timeInfo.Quarter));
            b4.KeyFrames.Add(new DiscreteDoubleKeyFrame(0, bpmControl.timeInfo.Whole));


            b1.Duration = bpmControl.timeInfo.Whole;
            b2.Duration = bpmControl.timeInfo.Whole;
            b3.Duration = bpmControl.timeInfo.Whole;
            b4.Duration = bpmControl.timeInfo.Whole;
            mt1.Duration = bpmControl.timeInfo.Whole;
            mt2.Duration = bpmControl.timeInfo.Whole;
            mt3.Duration = bpmControl.timeInfo.Whole;
            mt4.Duration = bpmControl.timeInfo.Whole;

            b1.RepeatBehavior = RepeatBehavior.Forever;
            b2.RepeatBehavior = RepeatBehavior.Forever;
            b3.RepeatBehavior = RepeatBehavior.Forever;
            b4.RepeatBehavior = RepeatBehavior.Forever;

            mt1.RepeatBehavior = RepeatBehavior.Forever;
            mt2.RepeatBehavior = RepeatBehavior.Forever;
            mt3.RepeatBehavior = RepeatBehavior.Forever; 
            mt4.RepeatBehavior = RepeatBehavior.Forever;

            info.Children.Add(b1);
            info.Children.Add(b2);
            info.Children.Add(b3);
            info.Children.Add(b4);

            info.Children.Add(mt1);
            info.Children.Add(mt2);
            info.Children.Add(mt3);
            info.Children.Add(mt4);

            info.Duration = bpmControl.timeInfo.Whole;
            
            Storyboard.SetTargetName(mt1, "Click1");
            Storyboard.SetTargetName(mt2, "Click2");
            Storyboard.SetTargetName(mt3, "Click3");
            Storyboard.SetTargetName(mt4, "Click4");


            
            Storyboard.SetTargetName(b1, "rectangle1");
            Storyboard.SetTargetProperty(b1, new PropertyPath("Opacity"));
            Storyboard.SetTargetName(b2, "rectangle2");
            Storyboard.SetTargetProperty(b2, new PropertyPath("Opacity"));
            Storyboard.SetTargetName(b3, "rectangle3");
            Storyboard.SetTargetProperty(b3, new PropertyPath("Opacity"));
            Storyboard.SetTargetName(b4, "rectangle4");
            Storyboard.SetTargetProperty(b4, new PropertyPath("Opacity"));
           
            info.RepeatBehavior = RepeatBehavior.Forever;
            info.Begin((BpmControl)obj);
        }

        public string Setup
        {
            get
            {

                object result = GetValue(SetupProperty);
                return (string)result;
            }
            set
            {

                SetValue(SetupProperty, value);
            }
        }

        #endregion


        #region LyricControlProperty
        public static readonly DependencyProperty LyricControlProperty =
            DependencyProperty.Register("LyricControl", typeof(string),
            typeof(BpmControl),
            new PropertyMetadata(OnLyricControlChanged));



        static private void OnLyricControlChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            
        }

        public string LyricControl
        {
            get
            {

                object result = GetValue(LyricControlProperty);
                return (string)result;
            }
            set
            {

                SetValue(LyricControlProperty, value);
            }
        }

        #endregion


    }



   public class TimeInfo
    {
        private TimeSpan oneMinute = TimeSpan.FromMinutes(1);
        double _bpm;
        private TimeSpan secondsPerBeat;
        int _timeSigTop;
        int _timeSigBottom;
        public double BPM
        {
            get
            {
                return _bpm;
            }
            set
            {
                _bpm = value;
                secondsPerBeat = new TimeSpan((long)(oneMinute.Ticks / _bpm));
            }
        }
        public TimeSpan Bar
        {
            get
            {
                return new TimeSpan(secondsPerBeat.Ticks * _timeSigTop);
            }
        }
        public int TimeSigTop
        {
            get
            {
                return _timeSigTop;
            }
            set
            {
                _timeSigTop = value;
            }
        }
        public int TimeSigBottom
        {
            get
            {
                return _timeSigBottom;
            }
            set
            {
                switch (value)
                {
                    case 1:
                    case 2:
                    case 4:
                    case 8:
                    case 16:
                    case 32:
                        _timeSigBottom = value;
                        break;
                    default:
                        throw new Exception("Invalid Bottom Part of Time Signature, must be 2^n n>=0");
                }

            }
        }
        public TimeSpan Quarter
        {
            get
            {
                return new TimeSpan(getBase().Ticks);
            }
        }
        private TimeSpan getBase()
        {
            switch (TimeSigBottom)
            {
                case 1:
                    return new TimeSpan(secondsPerBeat.Ticks / 4);

                case 2:
                    return new TimeSpan(secondsPerBeat.Ticks / 2);

                case 4:
                    return new TimeSpan(secondsPerBeat.Ticks);

                case 8:
                    return new TimeSpan(secondsPerBeat.Ticks * 2);

                case 16:
                    return new TimeSpan(secondsPerBeat.Ticks * 4);

                case 32:
                    return new TimeSpan(secondsPerBeat.Ticks * 8);

                default:
                    throw new Exception("Time Signature Bottom not set");
            }
        }
        public TimeSpan Half
        {
            get
            {
                return new TimeSpan(getBase().Ticks * 2);
            }
        }
        public TimeSpan Whole
        {
            get
            {
                return new TimeSpan(getBase().Ticks * 4);
            }
        }
        public TimeSpan Eigth
        {
            get
            {
                return new TimeSpan(getBase().Ticks / 2);
            }
        }
    }



}
